#ifndef _THREAD_HPP__
#define _THREAD_HPP__

#include <iostream>
#include <string>
#include <pthread.h>
#include <functional>
#include <sys/types.h>
#include <unistd.h>


//  V2
namespace ThreadModule
{
    enum class TSTATUS
    {
        NEW,//新建
       RUNNING,//启动
        STOP//停止
    };

    static int number = 1;

    template<typename T>
    class Thread
    {
        using func_t = std::function<void(T&)>;
    private:
        //int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
        //                 void *(*start_routine) (void *), void *arg);
        //成员变量，第一个参数是this，这样编不过，需加上static
        static void * Routine(void *args)
        {
            //static_cast：在c++用于类型转换
            Thread *t = static_cast<Thread<T> *>(args);
            t->_status = TSTATUS::RUNNING;
            t->_func(t->_data);
            return nullptr;
        }
        //开启分离
        void EnableDetach(){ _joinable = false;}
        
    public :
        Thread(func_t func,T &data)
        :_func(func)
        ,_data(data)
        ,_status(TSTATUS::NEW)
        ,_joinable(true)
        {
            _name = "Thread-"+std::to_string(number++);
            _pid = getpid();
        }
        ~Thread()
        {}
        //启动
        bool Start()
        {
            if(_status != TSTATUS::RUNNING)
            {
                //创建线程，创建好了就是启动的状态
                int n = ::pthread_create(&_tid,nullptr,Routine,this);
                if(n != 0) return false;
                return true;
            }
            return false;
        }
        //等待
        bool Join()
        {
            if(_joinable)
            {
                int n = ::pthread_join(_tid,nullptr);
                if(n != 0) return false;
                _status = TSTATUS::STOP;
                return true;
            }
            return false;

        }

        bool Stop()
        {
            if(_status == TSTATUS::RUNNING)
            {
                int n = ::pthread_cancel(_tid);
                if(n != 0) return false;
                _status = TSTATUS::STOP;
                return true;
            }
            return false;

        }

        //分离
        void Detach()
        {
            EnableDetach();
            ::pthread_detach(_tid);
        }
        std::string Name(){ return _name; }
        //是否被分离
        bool IsJoinable(){ return _joinable; }
        
    private:
        std::string _name;
        pthread_t _tid;
        pid_t _pid;
        bool _joinable;//是否是分离的，默认不是
        func_t _func;
        TSTATUS _status;//线程状态
        T &_data;
    };
}




// //    V 1
// namespace ThreadModule
// {
//     enum class TSTATUS
//     {
//         NEW,//新建
//        RUNNING,//启动
//         STOP//停止
//     };

//     using func_t = std::function<void()>;
//     static int number = 1;

//     class Thread
//     {
//     private:
//         //int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
//         //                 void *(*start_routine) (void *), void *arg);
//         //成员变量，第一个参数是this，这样编不过，需加上static
//         static void * Routine(void *args)
//         {
//             //static_cast：在c++用于类型转换
//             Thread *t = static_cast<Thread *>(args);
//             t->_status = TSTATUS::RUNNING;
//             t->_func();
//             return nullptr;
//         }
//         //开启分离
//         void EnableDetach(){ _joinable = false;}
        
//     public :
//         Thread(func_t func)
//         :_func(func)
//         ,_status(TSTATUS::NEW)
//         ,_joinable(true)
//         {
//             _name = "Thread-"+std::to_string(number++);
//             _pid = getpid();
//         }
//         ~Thread()
//         {}
//         //启动
//         bool Start()
//         {
//             if(_status != TSTATUS::RUNNING)
//             {
//                 //创建线程，创建好了就是启动的状态
//                 int n = ::pthread_create(&_tid,nullptr,Routine,this);
//                 if(n != 0) return false;
//                 return true;
//             }
//             return false;
//         }
//         //等待
//         bool Join()
//         {
//             if(_joinable)
//             {
//                 int n = ::pthread_join(_tid,nullptr);
//                 if(n != 0) return false;
//                 _status = TSTATUS::STOP;
//                 return true;
//             }
//             return false;

//         }

//         bool Stop()
//         {
//             if(_status == TSTATUS::RUNNING)
//             {
//                 int n = ::pthread_cancel(_tid);
//                 if(n != 0) return false;
//                 _status = TSTATUS::STOP;
//                 return true;
//             }
//             return false;

//         }

//         //分离
//         void Detach()
//         {
//             EnableDetach();
//             ::pthread_detach(_tid);
//         }
//         std::string Name(){ return _name; }
//         //是否被分离
//         bool IsJoinable(){ return _joinable; }
        
//     private:
//         std::string _name;
//         pthread_t _tid;
//         pid_t _pid;
//         bool _joinable;//是否是分离的，默认不是
//         func_t _func;
//         TSTATUS _status;//线程状态
//     };
// }

#endif


// #include <iostream>
// #include <vector>
// #include "Thread.hpp"
// #include <mutex>
// using namespace ThreadModule;

// #define NUM 4

// // 1. 锁本身是全局的，那么锁也是共享资源！谁保证锁的安全？？
// // pthread_mutex:加锁和解锁被设计成为原子的了
// // 2. 如何看待锁呢？二元信号量就是锁！
// //    2.1 加锁本质就是对资源展开预订！
// //    2.2 整体使用资源！！
// // 3. 如果申请锁的时候，锁被别人已经拿走了，怎么办？其他线程要进行阻塞等待
// // 4. 线程在访问临界区代码的时候，可以不可以切换？？可以切换！！
// //    4.1 我被切走的时候，别人能进来吗？？不能！我是抱着锁，被切换的！！不就是串行吗！效率低的原因！原子性！
// // 5. 不遵守这个约定？？bug！

// pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
// int ticketnum = 10000;//共享资源

// //c++定义一把锁
// std::mutex gmtx;

// class ThreadData
// {
// public:
//     std::string name;
//     pthread_mutex_t *lock_ptr;
// private:
// };

// void Ticket(ThreadData &td)
// {
//     while(true)
//     {
//         gmtx.lock();
//         //pthread_mutex_lock(td.lock_ptr);
//         if(ticketnum > 0)
//         {
//             usleep(1000);

//             //1.抢票
//             printf("get a new ticket, who get : %s , id : %d\n",td.name.c_str(),ticketnum--);

//             gmtx.unlock();
//             //pthread_mutex_unlock(td.lock_ptr);

//             //2.入库模拟
//             usleep(1000);
            
//         }
//         else
//         {
//             gmtx.unlock();
//             //pthread_mutex_unlock(td.lock_ptr);
//             break;
//         }
//     }
// }

// int main()
// {
//     //1.构建线程对象
//     std::vector<Thread<ThreadData>> threads;
//     for(int i= 0;i<NUM;i++)
//     {
//         ThreadData *td = new ThreadData();
//         td->lock_ptr = &lock;
//         threads.emplace_back(Ticket,*td);
//         td->name = threads.back().Name();
//     }

//     //2.启动线程
//     for(auto &thread:threads)
//     {
//         thread.Start();
//     }

//     //3.等待线程
//     for(auto &thread:threads)
//     {
//         thread.Join();
//     }
    
//     return 0;
// }

// namespace ThreadModule
// {
//     enum class TSTATUS
//     {
//         NEW,//新建
//        RUNNING,//启动
//         STOP//停止
//     };

//     using func_t = std::function<void()>;
//     static int number = 1;

//     class Thread
//     {
//     private:
//         //int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
//         //                 void *(*start_routine) (void *), void *arg);
//         //成员变量，第一个参数是this，这样编不过，需加上static
//         static void * Routine(void *args)
//         {
//             //static_cast：在c++用于类型转换
//             Thread *t = static_cast<Thread *>(args);
//             t->_status = TSTATUS::RUNNING;
//             t->_func();
//             return nullptr;
//         }
//         //开启分离
//         void EnableDetach(){ _joinable = false;}
        
//     public :
//         Thread(func_t func)
//         :_func(func)
//         ,_status(TSTATUS::NEW)
//         ,_joinable(true)
//         {
//             _name = "Thread-"+std::to_string(number++);
//             _pid = getpid();
//         }
//         ~Thread()
//         {}
//         //启动
//         bool Start()
//         {
//             if(_status != TSTATUS::RUNNING)
//             {
//                 //创建线程，创建好了就是启动的状态
//                 int n = ::pthread_create(&_tid,nullptr,Routine,this);
//                 if(n != 0) return false;
//                 return true;
//             }
//             return false;
//         }
//         //等待
//         bool Join()
//         {
//             if(_joinable)
//             {
//                 int n = ::pthread_join(_tid,nullptr);
//                 if(n != 0) return false;
//                 _status = TSTATUS::STOP;
//                 return true;
//             }
//             return false;

//         }

//         bool Stop()
//         {
//             if(_status == TSTATUS::RUNNING)
//             {
//                 int n = ::pthread_cancel(_tid);
//                 if(n != 0) return false;
//                 _status = TSTATUS::STOP;
//                 return true;
//             }
//             return false;

//         }

//         //分离
//         void Detach()
//         {
//             EnableDetach();
//             ::pthread_detach(_tid);
//         }
//         std::string Name(){ return _name; }
//         //是否被分离
//         bool IsJoinable(){ return _joinable; }
        
//     private:
//         std::string _name;
//         pthread_t _tid;
//         pid_t _pid;
//         bool _joinable;//是否是分离的，默认不是
//         func_t _func;
//         TSTATUS _status;//线程状态
//     };
// }

// #endif


// #include <iostream>
// #include <vector>
// #include "Thread.hpp"
// #include <mutex>
// using namespace ThreadModule;

// #define NUM 4

// // 1. 锁本身是全局的，那么锁也是共享资源！谁保证锁的安全？？
// // pthread_mutex:加锁和解锁被设计成为原子的了
// // 2. 如何看待锁呢？二元信号量就是锁！
// //    2.1 加锁本质就是对资源展开预订！
// //    2.2 整体使用资源！！
// // 3. 如果申请锁的时候，锁被别人已经拿走了，怎么办？其他线程要进行阻塞等待
// // 4. 线程在访问临界区代码的时候，可以不可以切换？？可以切换！！
// //    4.1 我被切走的时候，别人能进来吗？？不能！我是抱着锁，被切换的！！不就是串行吗！效率低的原因！原子性！
// // 5. 不遵守这个约定？？bug！

// pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
// int ticketnum = 10000;//共享资源

// //c++定义一把锁
// std::mutex gmtx;

// class ThreadData
// {
// public:
//     std::string name;
//     pthread_mutex_t *lock_ptr;
// private:
// };

// void Ticket(ThreadData &td)
// {
//     while(true)
//     {
//         gmtx.lock();
//         //pthread_mutex_lock(td.lock_ptr);
//         if(ticketnum > 0)
//         {
//             usleep(1000);

//             //1.抢票
//             printf("get a new ticket, who get : %s , id : %d\n",td.name.c_str(),ticketnum--);

//             gmtx.unlock();
//             //pthread_mutex_unlock(td.lock_ptr);

//             //2.入库模拟
//             usleep(1000);
            
//         }
//         else
//         {
//             gmtx.unlock();
//             //pthread_mutex_unlock(td.lock_ptr);
//             break;
//         }
//     }
// }

// int main()
// {
//     //1.构建线程对象
//     std::vector<Thread<ThreadData>> threads;
//     for(int i= 0;i<NUM;i++)
//     {
//         ThreadData *td = new ThreadData();
//         td->lock_ptr = &lock;
//         threads.emplace_back(Ticket,*td);
//         td->name = threads.back().Name();
//     }

//     //2.启动线程
//     for(auto &thread:threads)
//     {
//         thread.Start();
//     }

//     //3.等待线程
//     for(auto &thread:threads)
//     {
//         thread.Join();
//     }
    
//     return 0;
// }